今天來講解 this
相關的陷阱題
myName = '全域';
var person = {
myName: 'weiwei',
getName: function(){
return this.myName;
}
}
var getName = person.getName;
console.log(getName());
此時的 this
會指向全域,
因為 getName()
這種呼叫方式為簡易呼叫(Simple Call),
而此時的 this
只會跟呼叫方式有關,與定義過程無關
myName = '全域';
var obj = {
myName: 'weiwei',
fn: function(a, b, c){
return `${this.myName},${a},${b},${c}`;
}
}
var fnA = obj.fn;
var fnB = fnA.bind(null, 0);
console.log(fnB(1, 2));
此時會顯示 全域,0,1,2
,因為在非嚴謹模式下,
bind
所代入的 this
值為 null
,則函式中的 this
會指向全域,
而函式中的參數雖然在定義 fnB
時,只有帶入 0
,
但在 fnB(1, 2)
會將未取得值的參數依序代入值,
所以此時的 b
、 c
分別代入 1
、 2
的值,
如果我們要顯示 null,0,1,2
的話,可以將程式碼改成
myName = '全域';
var obj = {
myName: 'weiwei',
fn: function(a, b, c){
'use strict';
return `${this},${a},${b},${c}`;
}
}
var fnA = obj.fn;
var fnB = fnA.bind(null, 0);
console.log(fnB(1, 2));
此時只需將函式改為嚴謹模式,並且將函式中的 myName
去掉,
即可取得 null,0,1,2
這個值
var value = 'global';
var foo = {
value: 'local',
bar: function(){
return this.value;
}
}
// 直接執行
console.log(foo.bar());
// 賦值
console.log((foo.bar = foo.bar)());
// or
console.log((false || foo.bar)());
我們先看直接執行的部分,
在直接執行時,物件中 bar()
的 this
會指向前面的 foo
,
因此會回傳 local
,
接著講解後面兩個部分,
這兩個的概念基本上是一樣的,
foo.bar = foo.bar
和 false || foo.bar
都是表達式,
因此都會回傳值,而回傳值都是 bar
函式本身
而它的執行方式就跟簡易呼叫一樣,因此此時 this
會指向全域,
所以會回傳 global
var arr = [1, 2, 3].map(parseInt);
console.log(arr);
這題會回傳 [1, NaN, NaN]
,
我們先看 map()
,map()
的 ()
內為 callback function,
而所代入的前兩個參數分別為『陣列的值』、『值的索引位置』,
詳細說明可到 MDN 文件 中觀看,
接者我們看 parseInt()
,parseInt()
中能帶入兩個參數,分別為『待轉成數字的字串』、『進位數字』,
詳細說明可到 MDN 文件 中觀看,
所以這題的 parseInt()
中,所接收到的參數的值是『陣列的值』以及『值的索引位置』,
看完以上說明,可以將這題寫成以下型式
var arr = [1, 2, 3].map(function(item, i){
return parseInt(item, i)
});
console.log(arr);
而在 parseInt()
的 MDN 文件 中有寫到,當第二個參數為 0 時的情況:
如果 radix 是 undefined 或 0(或留空)的話,JavaScript 會:
- 如果 string 由 "0x" 或 "0X" 開始,radix 會變成代表十六進位的 16,並解析字串的餘數。
- 如果 string 由 0 開始,則 radix 會變成代表八進位的 8 或十進位的 10,但到底會變成 8 還是 10 則取決於各實做。ECMAScript 規定用代表十進位的 10,但也不是所有瀏覽器都支持。因此,使用 parseInt 時一定要指定 radix。
- 如果 string 由其他字串開始,radix 就會是十進位的 10。
如果第一個字串無法被解析為任何數字,parseInt 會回傳 NaN。
這邊直接針對呈現的結果來說明
parseInt(1, 0)
:因為第二個參數為 0,而以 MDN 文件說明來看,又因為第一個參數為 1,而非 0 或 0x 開頭,因此會是十進位,所以回傳 1
parseInt(2, 1)
:使用 1 來進位的數字根本不存在,因此回傳 NaN
parseInt(3, 2)
:這是使用二進位,而在二進位中不會有 3 這個數,因此回傳 NaN
以上就是今天的內容,終於完賽了,感謝觀看!!